// @flow
export default class SceneManager {

  static _init() {
    history.replaceState(null, null, "#");
    this.curScene = null;
    this.curRouter = null;
    this.routerMap = {};
    this.historyList = [];
  }

  static loadScene() {
    let { curScene } = SceneManager;
    if (curScene && !curScene.actived) return console.warn(`curSense not actived`);
    let args = Array.prototype.slice.call(arguments);
    let router = args[0];

    let taskList = [];
    let classSense = SceneManager.routerMap[router];
    let _proto = classSense.prototype;

    if (curScene && typeof curScene.beforeExit === "function") {
      let p1 = curScene.beforeExit();
      if (p1 instanceof Promise) taskList.push(p1);
    };

    if (typeof _proto.beforeEnter === "function") {
      let p2 =  _proto.beforeEnter();
      if (p2 instanceof Promise) taskList.push(p2);
    }

    if (typeof _proto.getAsset === "function" && !_proto.hasLoaded) {
      let asset = preProto.getAsset();
      if (Array.isArray(asset) && asset.length) {
        let fontAssets = asset.filter(v=> v.type==="font");
        fontAssets.forEach(fontRes => {
          let { url, type, name, setting } = fontRes;
          if (Laya.Text._bitmapFonts && Laya.Text._bitmapFonts[name]) return;
          let bitmapFont = new Laya.BitmapFont();
          if (setting) Object.assign(bitmapFont, setting);
          bitmapFont.loadFont(url);
          Laya.Text.registerBitmapFont(name, bitmapFont);
        });

        let p3 = new Promise(resolve=> {
          Laya.loader.load(asset, Laya.Handler.create(null, ()=> {
            _proto.hasLoaded = true;
            resolve();
          }));
        });
        taskList.push(p3);
      }
    }

    if (taskList.length > 0) {
      // showLoadding
      Promise.all(taskList).then(value=> {
        SceneManager.changeScense(args);
        // hideLoading
      });
    } else {
      SceneManager.changeScense(args);
    }

  }

  static changeScense(args) {
    let router = args[0];
    let { curScene, curRouter } = SceneManager;
    let classSense = SceneManager.routerMap[router];

    if (curRouter && curRouter!==router) SceneManager.pushHistory(curRouter);
    if (curScene) curScene.destroy(true);

    let Constructor = Function.bind.apply(classSense, [null].concat(args.slice[1]));
    let scense = new Constructor();

    Laya.stage.addChild(scense);
    Laya.timer.frameOnce(1, scense, ()=> {
      scense.__args = args;
      SceneManager.curScene = scense;
      SceneManager.curRouter = router;
      if (typeof scense.onEnter === "function") scense.onEnter();
      scense.actived = true;
    });
  }

  static goBack() {
    if (SceneManager.historyList.length>=1) {
      let router = SceneManager.historyList.pop();
      SceneManager.loadScene(router);
    }
  }

  static relaod() {
    let { curScene } = SceneManager;
    SceneManager.loadScene.apply(SceneManager, curScene.__args);
  }

  static pushHistory(router) {
    if (SceneManager.historyList.length >= 20) SceneManager.historyList.shift();
    SceneManager.historyList.push(router);
  }

  static regRouters(routers) {
    Object.assign(SceneManager.routerMap, routers);
  };
}

SceneManager._init();


export function scene(router) {
  return function (target) {
    SceneManager.routerMap[router] = target;
  };
}

/* window.addEventListener("hashchange", function () {
    if (lockedHash) return;
    let hash = location.hash;
    if (hash !== curRouter) {
        SenseManager.loadSense(hash.slice(1), null, null, true);
    }
}); */